import observe from "./observer/index";
import Watcher from "./observer/watcher";
export function initState(vm) {
  // 保存 $options
  const opts = vm.$options;
  if (opts.data) {
    // 若data存在 执行initData
    initData(vm);
  }
  // .. props methods computed watch
}

function initData(vm) {
  // 保存data
  let data = vm.$options.data;
  // 判断data 是否为函数 是 则执行 否则 返回这个对象或空对象
  data = vm._data = typeof data === "function" ? data.call(vm) : data || {};
  // 通过proxy方法劫持 将属性直接挂载到实例上
  for (let key in data) {
    proxy(vm, "_data", key);
  }
  // 观察者模式 深度监听 判断是对象 数组 原始值...
  observe(vm._data);
}

export function stateMixin(Vue) {
  /**
   * watch 定义
   * @param {*} expOrfn 监听表达式
   * @param {*} cb 回调
   * @param {*} options 配置
   */
  Vue.$watch = function (expOrfn, cb, options) {
    const vm = this;
    options = options || {};
    // 创建一个观察者
    const watcher = new Watcher(vm, expOrfn, cb, options);
    // 存在immediate 立即执行
    if (options.immediate) {
      cb.call(vm, watcher.value);
    }
  };
}

function proxy(vm, target, key) {
  // 数据劫持 defineProperty
  Object.defineProperty(vm, key, {
    enumerable: true,
    configurable: true,
    get() {
      // this.test = this._data.test
      return vm[target][key];
    },
    set(val) {
      // this.test = xxx >>> this._data.test = xxx
      vm[target][key] = val;
    },
  });
}
